-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consolidate fetch_* methods in a trait #3501
base: main
Are you sure you want to change the base?
Conversation
I don't think a trait for the user-facing part of the API is the right direction, precisely because it'll have to be imported everywhere which is going to be a huge headache. What I had in mind was absorbing all of the existing pub struct Query<DB, M = Identity> { ... }
pub type QueryAs<DB, T> = Query<DB, mapper::MapFromRow<T>>;
pub type QueryScalar<DB, T> = Query<DB, mapper::Scalar<T>>;
pub type Map<DB, F> = Query<DB, mapper::MapFn<F>>;
pub trait Mapper<DB: Database> {
type Output;
fn map(&mut self, row: DB::Row) -> sqlx::Result<Self::Output>;
}
pub mod mapper {
// `DB::Row` -> `DB::Row`
pub struct Identity;
// `DB::Row` -> `T` using `FromRow`
pub struct MapFromRow<T>(PhantomData<T>);
// `DB::Row` -> `T` using `Decode`
pub struct Scalar<T>(PhantomData<T>);
// `DB::Row` -> `T` where `F: FnMut(DB::Row) -> sqlx::Result<T>`
pub struct MapFn<F>(pub F);
} This would even allow custom What's missing is some sort of typestate that allows Maybe the solution for that is as simple as having a Addendum: on thinking about this more, I think it would be clearer if we used marker types for mutability like |
Also, if we're making breaking changes to the |
I also wanted to get rid of the Something like: pub struct Execute<DB> {
pub sql: SqlStr,
pub arguments: Option<DB::Arguments>,
pub persistent: bool,
pub limit: Option<usize>,
} |
@timvermeulen what do you think of the above? |
Your I'm now wondering if the main difference between these approaches is whether or not a trait needs to be imported to be able to call the
Does that sound like a fair comparison? I think I'm on board with the reasoning that a single |
Yeah, that's a non-starter.
I honestly don't use preludes much myself, so this would still be annoying to me. It's mostly there for people who want it. And besides, the It'd be really annoying to upgrade to have to go through and add
Yeah, there's also not much reason to reinvent the wheel here. The user can get all the flexibility they want out of |
Submitting this PR to see if there is any interest in something like this 🙂 Obviously it's maybe not ideal to have to import a trait to be able to call these methods.
Introduces the
Fetch
trait with required methodsfetch_many
andfetch_optional
(mirroring theExecutor
trait) that providesfetch
,fetch_all
,fetch_one
,map
, andtry_map
.The main benefits:
Query
,QueryAs
,QueryScalar
, andMap
query_as
/query_scalar
withmap
, which is slightly more convenient than fetching tuples and mapping the returnedVec